package com.ayq.activiti.manager.domain.activitimanager.service.impl;

import com.ayq.activiti.common.util.ConstantPool;
import com.ayq.activiti.manager.config.ActivitiIdGenerator;
import com.ayq.activiti.manager.domain.activitimanager.entity.ActivitiManager;
import com.ayq.activiti.manager.domain.activitimanager.repository.ActivitiManagerMapper;
import com.ayq.activiti.manager.domain.activitimanager.service.IActivitiManagerService;
import com.ayq.activiti.manager.domain.examinedistribution.entity.ActivitiExamineDistribution;
import com.ayq.activiti.manager.domain.examinedistribution.repository.ActivitiExamineDistributionMapper;
import com.ayq.activiti.manager.dto.ActivitiExamineDistributionDTO;
import com.ayq.activiti.manager.dto.ActivitiManagerDTO;
import com.ayq.activiti.manager.enums.ActivitiManagerEnum;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.ProcessDefinition;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author jobob
 * @since 2021-03-29
 */
@Service
public class ActivitiManagerServiceImpl extends ServiceImpl<ActivitiManagerMapper, ActivitiManager> implements IActivitiManagerService {

    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private ActivitiIdGenerator activitiIdGenerator;
    @Autowired
    private ActivitiExamineDistributionMapper activitiExamineDistributionMapper;

    /**
     * <p>绑定流程管理</p>
     * <p>方法名:addActivitiManager</p>
     *
     * @Author ayq
     * @Date 2021/3/31 9:24
     * @Param [activitiManagerDTO]
     * @Return void
     */
    @Override
    @Transactional
    public void addActivitiManager(ActivitiManagerDTO activitiManagerDTO) throws RuntimeException {
        ActivitiManagerEnum resultEnum = this.checkActivitiManager(activitiManagerDTO);
        if (activitiManagerDTO.getStatus() == 1) {
            QueryWrapper<ActivitiManager> wrapper = new QueryWrapper<ActivitiManager>();
            wrapper.eq(ConstantPool.COMPANY_ID, activitiManagerDTO.getCompanyId());
            this.remove(wrapper);
            QueryWrapper<ActivitiExamineDistribution> wrapper1 = new QueryWrapper<ActivitiExamineDistribution>();
            wrapper1.eq(ConstantPool.COMPANY_ID, activitiManagerDTO.getCompanyId());
            activitiExamineDistributionMapper.delete(wrapper1);
        }
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey(resultEnum.getKey()).latestVersion().singleResult();
        ActivitiManager activitiManager = ActivitiManager.builder().id(Long.parseLong(activitiIdGenerator.getNextId()))
                .createTime(new Date())
                .deploymentId(Long.parseLong(processDefinition.getDeploymentId()))
                .procdefId(processDefinition.getId())
                .procdefName(processDefinition.getName())
                .companyId(activitiManagerDTO.getCompanyId())
                .systemId(826414993158176768l)
                .businessId(826415375628369920l)
                .processName(processDefinition.getName())
                .createUsrId(activitiManagerDTO.getCreateUsrId())
                .procdefKey(processDefinition.getKey())
                .processVersion(processDefinition.getVersion())
                .createUsrName(activitiManagerDTO.getCreateUsrName())
                .build();
        this.save(activitiManager);
        InputStream resouceStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), processDefinition.getResourceName());
        XMLStreamReader xtr = null;
        try {
            XMLInputFactory xif = XMLInputFactory.newInstance();
            InputStreamReader in = new InputStreamReader(resouceStream, ConstantPool.UTF_8);
            xtr = xif.createXMLStreamReader(in);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
        BpmnModel model = new BpmnXMLConverter().convertToBpmnModel(xtr);
        Collection<FlowElement> flowElements = model.getMainProcess().getFlowElements();
        List<FlowElement> list = new ArrayList<FlowElement>();
        for (FlowElement e : flowElements) {
            String clazz = e.getClass().toString();
            if (clazz.endsWith(ConstantPool.USER_TASK)) {
                list.add(e);
            }
        }
        List<ActivitiExamineDistributionDTO> list1 = activitiManagerDTO.getList();
        if (list1 != null && list != null && list.size() == activitiManagerDTO.getList().size()) {
            for (int i = 0; i < list.size(); i++) {
                ActivitiExamineDistribution build = ActivitiExamineDistribution.builder()
                        .id(Long.parseLong(activitiIdGenerator.getNextId()))
                        .createUsrId(activitiManager.getCreateUsrId())
                        .createUsrName(activitiManager.getCreateUsrName())
                        .createTime(new Date())
                        .taskKey(list.get(i).getId())
                        .taskName(list.get(i).getName())
                        .activitiManagerId(activitiManager.getId())
                        .examineIds(list1.get(i).getExamineIds())
                        .examineNames(list1.get(i).getExamineNames())
                        .companyId(activitiManagerDTO.getCompanyId())
                        .systemId(826414993158176768l)
                        .businessId(826415375628369920l)
                        .build();
                activitiExamineDistributionMapper.insert(build);
            }
        } else {
            throw new RuntimeException(ConstantPool.CN_NINE);
        }
    }

    /**
     * <p>校验流程绑定</p>
     * <p>方法名:checkActivitiManager</p>
     *
     * @Author ayq
     * @Date 2021/4/8 15:17
     * @Param [activitiManagerDTO]
     * @Return org.ezca.esign.service.activiti.domain.activitimanager.entity.ActivitiManagerEnum
     */
    private ActivitiManagerEnum checkActivitiManager(ActivitiManagerDTO activitiManagerDTO) throws RuntimeException {
        ActivitiManagerEnum resultEnum = ActivitiManagerEnum.getResultEnum(activitiManagerDTO.getNumber());
        if (activitiManagerDTO.getCompanyId() == null) {
            throw new RuntimeException(ConstantPool.CN_TWELVE);
        }
        if (resultEnum.getNumber() == -1) {
            throw new RuntimeException(resultEnum.getKey());
        }
        if (activitiManagerDTO.getStatus() == null) {
            throw new RuntimeException(ConstantPool.CN_ELEVEN);
        }
        if (activitiManagerDTO.getStatus() != 0 && activitiManagerDTO.getStatus() != 1) {
            throw new RuntimeException(ConstantPool.CN_THIRTEEN + activitiManagerDTO.getStatus());
        }
        return resultEnum;
    }
}
